/****
 * Coprocessor 0 - Config/Config1/Config2/Config3/PRId
 * Configuration registers residing in CP0
 *
 * Config/Config1-3
 * CP0 defines 4 configuration fields.  These fields contain some read only data and
 * some r/w data.  Together they describe essential operating information about the
 * current architecture and configuration.
 *
 * PRId
 * Register contains information about the processor.
 **/


// Config Register
// Config Register Layout:
//  31  30       16 15  14   13 12  10 9    7 6   4  3  2     0
// | M |   IMPL   | BE |  AT  |  AR  |  MT  |  0  | VI |  K0  |

#define CFG_WRITE_MASK		0x7				// You can only write k0 from program space

#define CFG_CONTINUE		(1 << 31)		// Configuration continues in Config1
#define CFG_IMPL			0x7FFF0000		// Implementation specific
#define CFG_BIG_ENDIAN		(1 << 15)		// Endianess (1 for big)
#define CFG_ENCODING		0x6000			// Machine type, 0: MIPS32, 1: MIPS64 inst, 2: MIPS64 addr/inst	[AT]
#define CFG_ARCH			0x1C00			// Architecture level (0: release 1, 1: release 2)
#define CFG_MMU				0x380			// MMU type (0: none, 1: MIPS32/64 TLB, 3: BAT, MIPS32 FMT fixed)
#define CFG_VICACHE			(1 << 3)		// Set if L1 instruction cache uses virtual addresses
#define CFG_KS0_CACHE		0x7				// Determines the cache settings for kseg0, writable

#define SET_CFG_ENC(f, v)	REG_SET_BITS(f, CFG_ENCODING, 13, v)
#define GET_CFG_ENC(f)		REG_GET_BITS(f, CFG_ENCODING, 13)

#define SET_CFG_ARCH(f, v)	REG_SET_BITS(f, CFG_ARCH, 10, v)
#define GET_CFG_ARCH(f)		REG_GET_BITS(f, CFG_ARCH, 10)

#define SET_CFG_MMU(f, v)	REG_SET_BITS(f, CFG_MMU, 7, v)
#define GET_CFG_MMU(f)		REG_GET_BITS(f, CFG_MMU, 7)

#define SET_CFG_KS0(f, v)	REG_SET_BITS(f, CFG_KS0_CACHE, 0, v)
#define GET_CFG_KS0(f)		REG_GET_BITS(f, CFG_KS0_CACHE, 0)

// Valid encodings
enum {
	kCFGEncoding_MIPS32		= 0,	// MIPS32 instructions and address size
	kCFGEncoding_MIPS32_64	= 1,	// MIPS64 instructions, MIPS32 address size
	kCFGEncoding_MIPS64		= 2,	// MIPS64 instructions and address size
};

// Revision levels
enum {
	kCFGRevision_1			= 1,	// MIPS32/64 Release 1
	kCFGRevision_2			= 2,	// MIPS32/64 Release 2
};

// MMU Types
enum {
	kCFGMMUType_None		= 0,	// No address translation
	kCFGMMUType_TLB			= 1,	// Full MIPS32/64 TLB
	kCFGMMUType_BAT			= 2,	// Legacy translation
	kCFGMMUType_Fixed		= 3,	// Fixed mapping
};

// Config1 Register
// Config1 Layout:
//  31  30      25 24  22 21  19 18  16 15  13 12  10 9    7  6    6    4    3    2    1    0
// | M | MMUSize |  IS  |  IL  |  IA  |  DS  |  DL  |  DA  | C2 | MD | PC | WR | CA | EP | FP |
//               |      L1 ICache     |     L1 DCache      |

#define CFG1_WRITE_MASK		0x0				// No writable bits in Config1

#define CFG1_CONTINUE		(1 << 31)		// Configuration continues in Config2
#define CFG1_MMUSize		0x7E000000		// The TLB array has MMUSize+1 entries

// Instruction cache:
#define CFG1_IL1_IDX		0x1C00000		// Number of unique index positions in instruction cahce
											// index positions = 64x2^(S)
#define CFG1_IL1_LSIZE		0x380000		// Size of each cache line (if 0 there is no instr cache)
#define CFG1_IL1_ASSOC		0x70000			// Associativity of cache, cache is (A+1) way associative
											// IDX*ASSOC = total cache lines
											// NOTE: From now on assume all cache information bits work
											//       in this manner
// Data cache:
#define CFG1_DL1_IDX		0xE000			// Num index positions in data L1 cache
#define CFG1_DL1_LSIZE		0x1C00			// Cache lines for data cache
#define CFG1_DL1_ASSOC		0x380			// Associativity of data L1 cache

#define CFG1_HAS_CP2		(1 << 6)		// Set if CP2 exists
#define CFG1_HAS_OLD_MDMX	(1 << 5)		// Set if old MDMX ASE is in FPU
#define CFG1_HAS_PERF		(1 << 4)		// Set if there is at least one performance counter
#define CFG1_HAS_WATCH		(1 << 3)		// Set if there is a watchpoint register
#define CFG1_HAS_CCI		(1 << 2)		// Set if compressed code instruction set is avail
#define CFG1_HAS_EJTAG		(1 << 1)		// Set if EJTAG unit is available
#define CFG1_HAS_FPU		(1 << 0)		// Set if FPU is available


// Macros for packing cache data
#define SET_IL1_IDX(f, v)	REG_SET_BITS(f, CFG1_IL1_IDX, 22, v)
#define GET_IL1_IDX(f)		REG_GET_BITS(f, CFG1_IL1_IDX, 22)

#define SET_IL1_LSIZE(f, v)	REG_SET_BITS(f, CFG1_IL1_LSIZE, 19, v)
#define GET_IL1_LSIZE(f)	REG_GET_BITS(f, CFG1_IL1_LSIZE, 19)

#define SET_IL1_ASSOC(f, v)	REG_SET_BITS(f, CFG1_IL1_ASSOC, 16, v)
#define GET_IL1_ASSOC(f)	REG_GET_BITS(f, CFG1_IL1_ASSOC, 16)

#define SET_DL1_IDX(f, v)	REG_SET_BITS(f, CFG1_DL1_IDX, 13, v)
#define GET_DL1_IDX(f)		REG_GET_BITS(f, CFG1_DL1_IDX, 13)

#define SET_DL1_LSIZE(f, v)	REG_SET_BITS(f, CFG1_DL1_LSIZE, 10, v)
#define GET_DL1_LSIZE(f)	REG_GET_BITS(f, CFG1_DL1_LSIZE, 10)

#define SET_DL1_ASSOC(f, v)	REG_SET_BITS(f, CFG1_DL1_ASSOC, 7, v)
#define GET_DL1_ASSOC(f)	REG_SET_BITS(f, CFG1_DL1_ASSOC, 7)

// Config2 Regiser
// Config2 Layout:
//  31  30   28 27  24 23  20 19  16 15  12 11  8 7    4 3    0
// | M |  TU  |  TS  |  TL  |  TA  |  SU  | SS  |  SL  |  SA  |
//     |          L3 Cache         |         L2 Cache         |

#define CFG2_WRITE_MASK		0x0				// No writable bits in Config2

#define CFG2_CONTINUE		(1 << 31)		// Configuration continues in Config3
#define CFG2_L3_IMPL		0x70000000		// Implementation specific bits for L3 cache
#define CFG2_L3_IDX			0xF000000		// L3 cache index size
#define CFG2_L3_LSIZE		0xF00000		// L3 cache line size
#define CFG2_L3_ASSOC		0xF0000			// L3 cache associativity
#define CFG2_L2_IMPL		0xF000			// L2 cache impl bits
#define CFG2_L2_IDX			0xF00			// L2 cache index size
#define CFG2_L2_LSIZE		0xF0			// L2 cache line size
#define CFG2_L2_ASSOC		0xF				// L2 cache associativity

// Macros for packing cache data
#define SET_L3_IDX(f, v)	REG_SET_BITS(f, CFG2_L3_IDX, 22, v)
#define GET_L3_IDX(f)		REG_GET_BITS(f, CFG2_L3_IDX, 22)

#define SET_L3_LSIZE(f, v)	REG_SET_BITS(f, CFG2_L3_LSIZE, 19, v)
#define GET_L3_LSIZE(f)		REG_GET_BITS(f, CFG2_L3_LSIZE, 19)

#define SET_L3_ASSOC(f, v)	REG_SET_BITS(f, CFG2_L3_ASSOC, 16, v)
#define GET_L3_ASSOC(f)		REG_GET_BITS(f, CFG2_L3_ASSOC, 16)

#define SET_L2_IDX(f, v)	REG_SET_BITS(f, CFG2_L2_IDX, 13, v)
#define GET_L2_IDX(f)		REG_GET_BITS(f, CFG2_L2_IDX, 13)

#define SET_L2_LSIZE(f, v)	REG_SET_BITS(f, CFG2_L2_LSIZE, 10, v)
#define GET_L2_LSIZE(f)		REG_GET_BITS(f, CFG2_L2_LSIZE, 10)

#define SET_L2_ASSOC(f, v)	REG_SET_BITS(f, CFG2_L2_ASSOC, 7, v)
#define GET_L2_ASSOC(f)		REG_SET_BITS(f, CFG2_L2_ASSOC, 7)


// Config3 Register
// Config3 Layout:
//  31  30          11  10   9    8  7      6      5     4   3    2    1    0
// | M |      0      | DSPP |  0  | LPA | VEIC | VInt | SP | 0 | MT | SM | TL |

#define CFG3_WRITE_MASK		0x0				// No writable bits in Config3

#define CFG3_CONTINUE		(1 << 31)		// Configuration continues in other reg
#define CFG3_LARGE_ADDR		(1 << 7)		// Support for large physical addresses exists
#define CFG3_DSP_AVAIL		(1 << 10)		// Set when DSP support exists
#define CFG3_EIC_AVAIL		(1 << 6)		// Set when EIC support exists
#define CFG3_VINT_AVAIL		(1 << 5)		// Set when CPU supports vectored interrupts
#define CFG3_SMALL_PAGES	(1 << 4)		// Set when CPU supports smaller pages than 4kb
#define CFG3_MULT_THREAD	(1 << 2)		// Set when CPU supports multithreading
#define CFG3_SMART_AVAIL	(1 << 1)		// Set when CPU supports SmartMIPS ASE extension
#define CFG3_TRACE_AVAIL	(1 << 0)		// Set if instructuion trace is supported

// PRId Register
// PRId Layoyt:
//  31              24 23       16 15      8 7        0
// | Company Options | Company ID | CPU ID | Revision |

#define PRID_WRITE_MASK		0x0				// You can't write to PRId

#define PRID_COMPANY_OPTS	0xFF000000		// Implementation specific options
#define PRID_COMPANY_ID		0xFF0000		// Company ID from MIPS
#define PRID_CPU_ID			0xFF00			// CPU ID from MIPS
#define PRID_REVISION		0xFF			// CPU Revision

#define SET_PRID_OPTS(f, v)		REG_SET_BITS(f, PRID_COMPANY_OPTS, 24, v)
#define GET_PRID_OPTS(f)		REG_GET_BITS(f, PRID_COMPANY_OPTS, 24)

#define SET_PRID_COMPANY(f, v)	REG_SET_BITS(f, PRID_COMPANY_ID, 16, v)
#define GET_PRID_COMPANY(f)		REG_GET_BITS(f, PRID_COMPANY_ID, 16)

#define SET_PRID_CPUID(f, v)	REG_SET_BITS(f, PRID_CPU_ID, 8, v)
#define GET_PRID_CPUID(f)		REG_GET_BITS(f, PRID_CPU_ID, 8)

#define SET_PRID_REV(f, v)		REG_SET_BITS(f, PRID_REVISION, 0, v)
#define GET_PRID_REV(f)			REG_GET_BITS(f, PRID_REVISION, 0)

